<?php


namespace paper\file;


class File
{
    private $file;
    private string $error = "";
    private $tmpFileName = '';
    private array $validate = [];
    private $size;
    private $type;
    private $name;
    private $replace = false;
    private $saveName;
    private $fullSaveName;

    /**
     * @var string
     */
    private string $extension;
    private string $validateExt;

    public function __construct($file)
    {
        $this->file = $file;
        $this->tmpFileName = $file['tmp_name'];
    }

    /**
     * @param array $validate
     * @return $this
     */
    public function validate(array $validate): static
    {
        $this->validate = $validate;
        return $this;
    }

    public function replace($replace = false): static
    {
        $this->replace = $replace;
        return $this;
    }

    /**
     * @return string
     */
    public function getExtension(): string
    {
        return $this->extension;
    }

    /**
     * @return string
     */
    public function getError(): string
    {
        return $this->error;
    }

    /**
     * @return mixed
     */
    public function getSize(): int
    {
        return $this->size;
    }

    /**
     * @return string
     */
    public function getSaveName(): string
    {
        return $this->saveName;
    }

    /**
     * @return string
     */
    public function getName(): string
    {
        return $this->name;
    }

    /**
     * @return mixed
     */
    public function getFullSaveName(): mixed
    {
        return $this->fullSaveName;
    }

    public function save($path = './upload/', $create = false): bool
    {
        if ($this->file['error'] !== UPLOAD_ERR_OK) {
            $this->error = $this->file['error'];
            return false;
        }

        if (!is_uploaded_file($this->tmpFileName)) {
            $this->error = '错误的文件类型：不是上传的文件';
            return false;
        }
        $this->size = $this->file['size'];
        $this->type = $this->file['type'];
        $this->name = $this->file['name'];

        $pathinfo = explode(".", $this->name, 2);
        $this->validateExt = pathinfo($this->name, PATHINFO_EXTENSION);
        if (count($pathinfo) != 2) {
            $this->error = "文件必须带有后缀才可上传";
            return false;
        }
        $this->extension = $pathinfo[1];

        if ($this->validate) {
            //验证文件后缀名
            if (isset($this->validate['ext'])) {
                $allow = [];
                if (is_string($this->validate['ext'])) {
                    $allow = explode(',', strtolower($this->validate['ext']));
                } else {
                    $allow = $this->validate['ext'];
                }
                if (!in_array($this->validateExt, $allow)) {
                    $this->error = "错误的文件扩展名!上传的扩展为： $this->extension";
                    return false;
                }
            }

            //验证文件大小
            if (isset($this->validate['size'])) {
                if ($this->size > $this->validate['size']) {
                    $this->error = '错误的文件大小';
                    return false;
                }
            }
        }

        if (!is_dir($path)) {
            if ($create) {
                mkdir($path,777,true);
            } else {
                $this->error = "上传的路径不存在";
                return false;
            }
        }
        $subDir = date("Ymd", time());
        $savePath = $path;
        $saveName = $subDir . '/' . $this->buildSaveName();
        $this->fullSaveName = $path . $saveName;

        $this->saveName = $saveName;

        if (!is_dir($savePath . $subDir)) {
            mkdir($savePath . $subDir);
        }

        if ($this->replace == false && is_file($savePath . '/' . $saveName)) {
            $this->error = '文件已经存在';
            return false;
        }

        if (!move_uploaded_file($this->tmpFileName, $savePath . $saveName)) {
            $this->error = '文件移动保存失败';
            return false;
        }

        return true;
    }

    /**
     * @return string
     */
    public function getValidateExt(): string
    {
        return $this->validateExt;
    }

    public function buildSaveName(): string
    {
        $name = md5($this->name . time() . getmypid());
        return $name . '.' . $this->extension;
    }
}